package com.songlanyun.modules.goods.entity;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.*;


import java.io.IOException;
import java.math.BigDecimal;
import java.io.Serializable;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.type.TypeReference;
import com.songlanyun.common.drive.RootEntity;
import com.songlanyun.common.enums.GoodsConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.PasswordUtil;
import com.songlanyun.common.utils.SpringContextUtils;
import com.songlanyun.common.utils.custom.ClassConvertUtils;
import com.songlanyun.common.validator.group.AddGroup;
import com.songlanyun.common.validator.group.UpdateGroup;
import com.songlanyun.modules.category.entity.SystemProductCategoryEntity;
import com.songlanyun.modules.category.service.SystemProductCategoryService;
import com.songlanyun.modules.exception.GoodsExceptionEnum;
import com.songlanyun.modules.goods.model.values.GoodsSkuTableItem;
import com.songlanyun.modules.goods.model.vo.SkuComItemVo;
import com.songlanyun.modules.goods.service.GoodsAuthShopService;
import com.songlanyun.modules.goods.service.GoodsContentService;
import com.songlanyun.modules.goods.service.GoodsSkuService;
import com.songlanyun.modules.goodsuserdiscount.entity.GoodsUserDiscountConfig;
import com.songlanyun.modules.goodsuserdiscount.service.GoodsUserDiscountConfigService;
import com.songlanyun.modules.group.entity.ProductGoodsGroupEntity;
import com.songlanyun.modules.group.model.vo.GoodsGroupSlim;
import com.songlanyun.modules.group.service.ProductGoodsGroupService;
import com.songlanyun.modules.hxcategory.entity.HxCategoryEntity;
import com.songlanyun.modules.hxcategory.service.HxCategoryEntityService;
import com.songlanyun.modules.inter.ISaleEntity;
import com.songlanyun.modules.shop.entity.ShopEntity;
import com.songlanyun.modules.shop.service.ShopService;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Length;
import org.springframework.boot.autoconfigure.amqp.RabbitRetryTemplateCustomizer;

import javax.persistence.Table;
import javax.validation.constraints.*;

/**
 * 商家所发商品表
 *
 * @author lubo
 * @email sunlightcs@gmail.com
 * @date 2020-11-05 10:01:59
 */
@Data
@TableName("yxt_product_goods")
public class Goods extends RootEntity<Long, Goods> implements ISaleEntity, Serializable {
    private static final long serialVersionUID = 1L;

    {
        initSaleNum = 0;
        realSaleNum = 0;
        resultSaleNum = 0;
        shopId = 0L;
        minSalePrice = BigDecimal.ZERO;
        maxSalePrice = BigDecimal.ZERO;
        minMarketPrice = BigDecimal.ZERO;
        maxMarketPrice = BigDecimal.ZERO;
        minExchangePoint = BigDecimal.ZERO;
        maxExchangePoint = BigDecimal.ZERO;
        title = "";
        videoUrl = "";
        shortTitle = "";
        spuCode = "";
        limitBuyNum = 0;
        categoryId = 0L;
        freightTemplateId = 0;
        pointGoods = false;
        remark = "";
        verifyStatus = GoodsConstant.VerifyStatus.WAIT;
        deleted = 0;
        sort = 0;
        platformStore = false;
        pv = 0L;
        openUserDiscount = true;
        hot = false;
        newGoods = false;
        recommend = false;
        average = new BigDecimal("5");
        giftType = GoodsConstant.GiftType.NO;

        thirdSpuId = 0L;
        third = false;
        source = 0;



    }

    private Integer isOfflineProduct;

    @TableId
    @NotNull(message = "修改时必须指定商品Id", groups = {UpdateGroup.class})
    @Null(message = "新增时不能指定商品Id", groups = {AddGroup.class})
    private Long id;
    /**
     * 发布的商家店铺Id
     */
    private Long shopId;


    /**
     * 候鸟商品id
     */
    private String houniaoSpuId;

    /**
     * 贸易类型id，1=保税直供，2=完税进口，3=国内贸易，4=香港直邮，5=海外直邮
     */
    private Integer tradeTypeId;

    /**
     * 商品分区特征(0普通商品,1激活区商品,2复购区商品)
     */
    private GoodsConstant.AreaFeature areaFeature = GoodsConstant.AreaFeature.GENERAL;



    /**
     * 是否开启会员折扣
     */
    private Boolean openUserDiscount;

    /**
     * 最低售价
     */
    private BigDecimal minSalePrice;
    /**
     * 最高售价
     */
    private BigDecimal maxSalePrice;
    /**
     * 最低市场价
     */
    private BigDecimal minMarketPrice;
    /**
     * 最高市场价
     */
    private BigDecimal maxMarketPrice;
    /**
     * 最低兑换积分
     */
    private BigDecimal minExchangePoint;
    /**
     * 最高兑换积分
     */
    private BigDecimal maxExchangePoint;
    /**
     * 商品标题
     */
    @NotBlank(message = "商品标题名称不能为空", groups = {AddGroup.class, UpdateGroup.class})
    @Length(min = 1, max = 400, message = "商品标题名称长度在1-50个字", groups = {AddGroup.class, UpdateGroup.class})
    private String title;

    /**
     * 主图视频
     */
    private String videoUrl;
    /**
     * 短标题
     */
    @Length(min = 0, max = 10, message = "商品短标题名称长度在0-10个字", groups = {AddGroup.class, UpdateGroup.class})
    private String shortTitle;

    /**
     * SPU编码
     */
    @Length(min = 0, max = 30, message = "SPU编码名称长度在1-30个字", groups = {AddGroup.class, UpdateGroup.class})
    private String spuCode;

    /**
     * 限购数量(0：代表不限购，大于0，为限购)
     */
    @Min(value = 0, message = "限购数最小是零", groups = {AddGroup.class, UpdateGroup.class})
    @Max(value = 99999999, message = "初始化销量最大是99999999", groups = {AddGroup.class, UpdateGroup.class})
    private Integer limitBuyNum;


    /**
     * 所属商品分类id
     */
    private Long categoryId;


    /**
     * 所属惠选商品分类id
     */
    private Long hxCategoryId;

    @TableField(exist = false)
    @JsonIgnore
    private HxCategoryEntity hxCategory;

    /**
     * 加载所属分类
     *
     * @return
     */
    public HxCategoryEntity loadHxCategory() {
        if (hxCategory == null) {
            hxCategory = ((HxCategoryEntityService) SpringContextUtils.getBean("hxCategoryService")).getById(this.getHxCategoryId());
        }
        return hxCategory;
    }


    /**
     * 所属商品分类实体
     */
    @TableField(exist = false)
    @JsonIgnore
    private SystemProductCategoryEntity category;


    /**
     * 所属商家
     */
    @TableField(exist = false)
    @JsonIgnore
    private ShopEntity shop;

    /**
     * 加载所属分类
     *
     * @return
     */
    public SystemProductCategoryEntity loadCategory() {
        if (category == null) {
            category = ((SystemProductCategoryService) SpringContextUtils.getBean("systemProductCategoryService")).getById(this.getCategoryId());
        }
        return category;
    }


    /**
     * 加载商品详情
     */
    @TableField(exist = false)
    private String mobileDetail;

    /**
     * 加载商品详情
     *
     * @return
     */
    public String loadContent() {
        if (mobileDetail == null) {
            mobileDetail = ((GoodsContentService) SpringContextUtils.getBean("goodsContentService")).getByGoodsId(this.getId()).getMobileDetail();
        }
        return mobileDetail;
    }


    /**
     * 加载商家店铺
     *
     * @return
     */
    public ShopEntity loadShop() {
        if (shop == null) {
            shop = ((ShopService) SpringContextUtils.getBean("yxtShopService")).getById(this.getShopId());
        }
        return shop;
    }

    /**
     * 运模模板id
     */

    private Integer freightTemplateId;

    /**
     * 积分类型（0，不是积分商品，1积分兑换商品）
     */
    private Boolean pointGoods;


//    /**
//     * 是否是积分兑换（0，不是积分兑换,只是要使用积分，1积分兑换）
//     */
//    private Boolean exchange;


    /**
     * 浏览量
     */
    private Long pv;
    /**
     * 商品介绍
     */
    @Length(max = 150, message = "商品简介最大字数不能超过150字")
    private String remark;

    /**
     * 0待审核，1审核通过，2审核不通过
     */
    private GoodsConstant.VerifyStatus verifyStatus;

    /**
     * 审核说明
     */
    private String verifyRemark;
    /**
     * 最后审核时间
     */
    private Date lastVerifyTime;
    /**
     *
     */
    @TableLogic
    private Integer deleted;
    /**
     * 顺序
     */
    @Max(value = 999999, message = "顺序值最大999999", groups = {AddGroup.class, UpdateGroup.class})
    @Min(value = 0, message = "最小顺序值是0", groups = {AddGroup.class, UpdateGroup.class})
    private Integer sort;
    /**
     * 是否是平台店的商品
     */
    private Boolean platformStore;

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    /**
     *
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;


    //销量相关===================================================================================
    /**
     * 初始化销量
     */
    @Min(value = 0, message = "初始化销量最小是零", groups = {AddGroup.class, UpdateGroup.class})
    @Max(value = 99999999, message = "初始化销量最大是99999999", groups = {AddGroup.class, UpdateGroup.class})
    private Integer initSaleNum;

    /**
     * 真实销量
     */
    private Integer realSaleNum;
    /**
     * 输出销量
     */
    private Integer resultSaleNum;

    /**
     * 在实体添加，修改之前调用，在销量增减时也会调用一次
     */
    public void computeResultSaleNum() {
        this.resultSaleNum = this.initSaleNum + this.realSaleNum;
    }

    /**
     * 增加销量
     *
     * @param num
     */
    public void incSaleNum(int num) {
        this.realSaleNum += num;
        this.computeResultSaleNum();
    }

    /**
     * 减少销量
     *
     * @param num
     */
    public void decSaleNum(int num) {
        this.realSaleNum -= num;
        this.computeResultSaleNum();
    }

    //销量相关结束===================================================================================


    //所属分组================================================================================
    /**
     * 所属分组
     */
    @TableField(exist = false)
    private List<GoodsGroupSlim> groupList;

    /**
     * 加载所属商品分组（在需要后端需要加载的时候手动加载）
     *
     * @return
     */
    @JsonIgnore
    public List<GoodsGroupSlim> loadPublishAuthGroupList() {

        if (groupList == null) {
            ProductGoodsGroupService service = ((ProductGoodsGroupService) SpringContextUtils.getBean("productGoodsGroupService"));
            groupList = service.selectGoodsGroupRelation(this.loadPublishAuth().getId());
        }
        return groupList;
    }

    //商品规格skus相关================================================================
    /**
     * 商品规格
     */
    @TableField(exist = false)
    private List<GoodsSku> goodsSkuList;

    /**
     * 加载所有商品的规格
     *
     * @return
     */
    @JsonIgnore
    public List<GoodsSku> loadGoodsSkuList() {
        if (goodsSkuList == null) {
            GoodsSkuService service = ((GoodsSkuService) SpringContextUtils.getBean("goodsSkuService"));
            goodsSkuList = service.loadGoodsSkuList(this.getId());

        }
        return goodsSkuList;
    }

    /**
     * 通过指定规格HashCode，加载商品的规格
     *
     * @return
     */
    @JsonIgnore
    public GoodsSku getGoodsSku(String skuHashCode) {
        Optional<GoodsSku> optional = this.loadGoodsSkuList().stream().filter(item -> item.getSkuSetName().equals(skuHashCode)).findFirst();
        if (optional.isPresent()) {
            return optional.get();
        }
        return new GoodsSku();
    }

    //商品规格skus相关结束================================================================


    /**
     * 通过规格处理价格方面的容余字段
     *
     * @param goodsSkuList
     */
    public void handelGoodsSkuList(List<GoodsSku> goodsSkuList) {
        this.setGoodsSkuList(goodsSkuList);
        if (this.goodsSkuList.size() == 0) {
            throw new Error("必须选择规格");
        }
        this.goodsSkuList.forEach((item) -> {
            if (item.getSingleGoodsId() == 0) {
                throw new Error("必须存在单品");
            }
        });

        GoodsSku minSku = Collections.min(this.goodsSkuList, Comparator.comparing(GoodsSku::getSalePrice));
        this.minSalePrice = minSku.getSalePrice();

        GoodsSku maxSku = Collections.max(this.goodsSkuList, Comparator.comparing(GoodsSku::getSalePrice));
        this.maxSalePrice = maxSku.getSalePrice();


        GoodsSku minMarkSku = Collections.min(this.goodsSkuList, Comparator.comparing(GoodsSku::getMarketPrice));
        this.minMarketPrice = minMarkSku.getMarketPrice();
        GoodsSku maxMarkSku = Collections.max(this.goodsSkuList, Comparator.comparing(GoodsSku::getMarketPrice));
        this.maxMarketPrice = maxMarkSku.getMarketPrice();


        GoodsSku minExchangePointSku = Collections.min(this.goodsSkuList, Comparator.comparing(GoodsSku::getExchangePoint));
        this.minExchangePoint = minExchangePointSku.getExchangePoint();
        GoodsSku maxExchangePointSku = Collections.max(this.goodsSkuList, Comparator.comparing(GoodsSku::getExchangePoint));
        this.maxExchangePoint = maxExchangePointSku.getExchangePoint();

    }

    //商品规格表相关=====================================================================
    /**
     * 商品的规格表
     * [
     * {"head":{"id":123,"name":"颜色"},"values":[{"id":12344,"name":"白色"},{"id":123,"name":"红色"}]}
     * {"head":{"id":12443,"name":"尺码"},"values":[{"id":1234444,"name":"175"},{"id":12443,"name":"180"}]}
     * {"head":{"id":124435,"name":"性别"},"values":[{"id":24324,"name":"男"},{"id":324323,"name":"女"}]}
     * ]
     */
    @TableField(exist = false)
    private List<GoodsSkuTableItem> skuTable;

    public void setSkuTable(List<GoodsSkuTableItem> skuTable) {
        this.skuTable = skuTable;
        this.skuTableValue = JSONUtil.toJsonStr(this.skuTable);
    }

    @JsonIgnore
    private String skuTableValue;

    /**
     * 对于从数据库映射的数据，除了设置相应的值，还需要映射成对象(手动调用)
     */
    public void setSkuTableValue(String skuTableValue) {
        this.skuTableValue = skuTableValue;
        if (StringUtils.isEmpty(this.skuTableValue)) {
            this.skuTable = new ArrayList<>();
        } else {
            try {
                this.skuTable = ClassConvertUtils.stringToClassSnake(skuTableValue, new TypeReference<List<GoodsSkuTableItem>>() {
                });
            } catch (IOException e) {
                throw new RRException("商品规格表无法转Map");
            }
        }
    }
    //商品规格表相关结束=====================================================================


    //商品图片相关===================================================================================
    /**
     * 商品图片 商品图片（5张）
     */
    @JsonIgnore
    private String imagesValue;

    @TableField(exist = false)
    private List<String> images;

    public List<String> getImages() {
        return images;
    }

    public void setImages(List<String> images) {
        this.images = images;
        if (images.isEmpty()) {
            throw new Error("商品图片不能为空");
        }
        this.imagesValue = JSONUtil.toJsonStr(this.images);
        setCover(images.get(0));
    }

    /**
     * 把字符串映射成对象（多图）
     */
    public void setImagesValue(String imagesValue) {
        this.imagesValue = imagesValue;
        if (StringUtils.isEmpty(this.imagesValue)) {
            setImages(new ArrayList<>());
        } else {
            try {
                setImages(ClassConvertUtils.stringToClassSnake(imagesValue, new TypeReference<List<String>>() {
                }));
            } catch (IOException e) {
                throw new RRException("商品图片无法转List");
            }

        }
    }

    /**
     * 封面图片
     */
    private String cover;

    //商品图片相关===================================================================================

    //标签相关===================================================================================
    /**
     * 热销
     */
    private Boolean hot;

    /**
     * 是否是新品
     */
    private Boolean newGoods;

    /**
     * 是否推荐
     */
    private Boolean recommend;

    /**
     * 评价分数
     */
    private BigDecimal average;

    /**
     * 礼包类型0非礼包，1.礼包282，2.礼包6750
     */
    private GoodsConstant.GiftType giftType;


    //标签相关结束===================================================================================


    /**
     * 当前商品哪些人有权营权限
     */
    @JsonIgnore
    @TableField(exist = false)
    private List<GoodsAuthShop> authList;

    public List<GoodsAuthShop> loadAuthList() {
        if (authList == null) {
            GoodsAuthShopService service = ((GoodsAuthShopService) SpringContextUtils.getBean("goodsAuthShopService"));
            LambdaQueryWrapper<GoodsAuthShop> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(GoodsAuthShop::getGoodsId, this.getId());
            authList = service.list(wrapper);
        }
        return authList;

    }

    /**
     * 获得发布者的经营权限
     *
     * @return
     */
    public GoodsAuthShop loadPublishAuth() {
        GoodsAuthShopService service = ((GoodsAuthShopService) SpringContextUtils.getBean("goodsAuthShopService"));

        GoodsAuthShop first = service.getOne(new LambdaQueryWrapper<GoodsAuthShop>()
                .eq(GoodsAuthShop::getPublishShopId, this.getShopId())
                .last("limit 1")
        );
        if (first != null) {
            return first;
        }

        throw new RRException(GoodsExceptionEnum.PUBLISH_AUTH_NOT_EXISTS);

    }

    /**
     * 根据商家获得经营权限
     *
     * @return
     */
    public GoodsAuthShop loadAuthByShop(Long shopId) {
        Optional<GoodsAuthShop> first = this.loadAuthList().stream().filter(o -> o.getAuthorizeShopId().equals(shopId)).findFirst();
        if (first.isPresent()) {
            return first.get();
        }
        return null;
    }

    @JsonIgnore
    @TableField(exist = false)
    private GoodsUserDiscountConfig goodsUserDiscountConfig;

    /**
     * 加载当前商品的会员折扣配置
     *
     * @return
     */
    public GoodsUserDiscountConfig loadGoodsUserDiscountConfig() {
        if (goodsUserDiscountConfig == null) {
            goodsUserDiscountConfig = ((GoodsUserDiscountConfigService) SpringContextUtils.getBean("goodsUserDiscountConfigService")).getByGoodsId(this.getId());
        }
        return goodsUserDiscountConfig;
    }

    /**
     * 是否通过审核
     *
     * @return
     */
    @Override
    public boolean isVerify() {
        return GoodsConstant.VerifyStatus.YES.equals(this.getVerifyStatus());
    }

    @Override
    public Long getIdentity() {
        return getId();
    }

    /**
     * 平台商家指定商品是否可以代销
     */
    private Boolean ableProxySale;

    /**
     * 赠送积分（只有平台商家才可以赠送积分）
     */
    private BigDecimal givePoint;


    /**
     * 赠送贡献值
     */
    private BigDecimal consumptionValue;


    /**
     * 是否免费
     */
    private Boolean free;


    /**
     * 总库存
     */
    @TableField(exist = false)
    private Integer residualInventory;

    /**
     * 计算库存
     *
     * @return
     */
    public List<SkuComItemVo> loadResidualInventory() {

        GoodsSkuService goodsSkuService = (GoodsSkuService) SpringContextUtils.getBean("goodsSkuService");
        List<SkuComItemVo> list = goodsSkuService.loadSkuItemList(getId());
        Map<Long, Integer> temp = new HashMap<>();
        Integer total = 0;
        list.forEach(o -> {
            if (!temp.containsKey(o.getSingleGoodsId())) {
                temp.put(o.getSingleGoodsId(), o.getAbleStock());
            }
        });
        total = temp.values().stream().mapToInt(integer -> integer).sum();
        this.residualInventory = total;
        return list;
    }


    //为第三方商品补加的字段=========================================================================

    /**
     * 第三方商品的SpuId;
     */
    private Long thirdSpuId;

    /**
     *  是否是第三方商品
     */
    private Boolean third;

    /**
     * 如果是第三方商品，来源有效
     * 来源1云仓2京东6阿里巴巴7天猫11华南一仓14华东一仓15淘宝99候鸟
     */
    private Integer source;
}
